/*
 * Copyright 1999-2015 dangdang.com.
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * </p>
 */

package com.niiwoo.civet.account.sharding;

import com.dangdang.ddframe.rdb.sharding.api.ShardingValue;
import com.dangdang.ddframe.rdb.sharding.api.strategy.database.SingleKeyDatabaseShardingAlgorithm;
import com.google.common.collect.Range;
import org.joda.time.DateTime;
import org.joda.time.DateTimeFieldType;

import java.util.Collection;
import java.util.LinkedHashSet;

/**
 * 按月取模分库，总共12个库
 */
public class YearMonthDataBaseShardingAlgorithm implements SingleKeyDatabaseShardingAlgorithm<String> {
    
    @Override
    public String doEqualSharding(final Collection<String> availableTargetNames, final ShardingValue<String> shardingValue) {
        String yearMonthDay = shardingValue.getValue();
        int month = new DateTime(yearMonthDay).get(DateTimeFieldType.monthOfYear());

        for (String each : availableTargetNames) {
            if (each.endsWith("_" + month % availableTargetNames.size())) {
                return each;
            }
        }
        throw new UnsupportedOperationException();
    }

    @Override
    public Collection<String> doInSharding(final Collection<String> availableTargetNames, final ShardingValue<String> shardingValue) {
        Collection<String> result = new LinkedHashSet<>(availableTargetNames.size());
        Collection<String> yearMonthDayList = shardingValue.getValues();

        for (String yearMonthDay : yearMonthDayList) {
            int month = new DateTime(yearMonthDay).get(DateTimeFieldType.monthOfYear());

            for (String each : availableTargetNames) {
                if (each.endsWith("_" + month % availableTargetNames.size())) {
                    result.add(each);
                }
            }
        }
        return result;
    }
    
    @Override
    public Collection<String> doBetweenSharding(final Collection<String> availableTargetNames, final ShardingValue<String> shardingValue) {
        Collection<String> result = new LinkedHashSet<>(availableTargetNames.size());
        Range<String> range = shardingValue.getValueRange();

        DateTime startDateTime = new DateTime(range.lowerEndpoint());
        DateTime endDateTime = new DateTime(range.upperEndpoint());
        for (DateTime date = startDateTime; !date.isAfter(endDateTime); date = date.plusMonths(1)){
            int day = new DateTime(date).getDayOfMonth();
            for (String each : availableTargetNames) {
                if (each.endsWith("_" + day % availableTargetNames.size())) {
                    result.add(each);
                }
            }
        }

        return result;
    }
}